/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package yuhuibear.poat.query;

import yuhuibear.poat.exception.ParametersMissMatch;
import yuhuibear.poat.object.bean.PersistentClassLoader;
import yuhuibear.poat.util.StringBufferTool;

/**
 * 更新模式下如果不指定条件将直接使用 primary key 作为对象的定位的条件。
 * 
 * @author Administrator
 */
public class SQLBuilder {

	public static final String FROM = " from ";

	public static final String WHERE = " where ";

	public static final String AND = " and ";

	public static final String SET = " set ";

	public static final String AS = " as ";

	public static final String DISTINCT = " distinct ";

	private String sql = "";

	private PersistentClassLoader bAnalyzer;

	public SQLBuilder(PersistentClassLoader ba) {
		bAnalyzer = ba;

	}

	/**
	 * 用@see QueryAssistor 产生sql 语句.
	 * 
	 * @param isql
	 * @return
	 * @throws java.lang.Exception
	 */
	public String getSQL(QueryAssistor isql) throws Exception {
		StringBuffer sqlSb = new StringBuffer();
		sqlSb.append(isql.getCmd());
		switch (isql.getCmdType()) {
			// insert
			case ObjectQuery.INSERT: {
				if (isql.hasAs()) { throw new ParametersMissMatch("no statements AS needed, while INSERT"); }
				sqlSb.append(isql.getTarget());
				sqlSb.append(" (");
				String[] names = bAnalyzer.analyse(isql.getTargetType()).getDBNameOfAttributes();
				StringBufferTool.appendWithGap(sqlSb, names, ", ");
				sqlSb.append(" ) values (");
				StringBufferTool.appendWithGap(sqlSb, "?", names.length, ", ",
												", ");
				sqlSb.append(")");
				break;
			}
				// select
			case ObjectQuery.SELECT: {
				sqlSb.append(isql.getTarget());
				String str = isql.getFrom();
				if (str != null && str.length() > 0) {
					sqlSb.append(FROM);
					sqlSb.append(str);
				}
				str = isql.getConditions();
				if (str != null) {
					sqlSb.append(WHERE);
					sqlSb.append(str);
				}
				str = isql.getOrderBy();
				if (str != null) {
					sqlSb.append(" ");
					sqlSb.append(str);
				}
				str = isql.getGroupBy();
				if (str != null) {
					sqlSb.append(" ");
					sqlSb.append(str);
				}
				str = isql.getPageInfro();
				if (str != null) {
					sqlSb.append(str);
				}
				break;
			}
				// update
			case ObjectQuery.UPDATE: {
				sqlSb.append(isql.getTarget());
				sqlSb.append(SET);
				String atrbs = isql.getAttributes();
				if (atrbs == null) {
					String[] names = bAnalyzer.analyse(isql.getTargetType()).getDBNameOfAttributes();
					StringBufferTool.appendWithGap(sqlSb, names, " = ?, ", ", ");
				}
				else {
					sqlSb.append(atrbs);
				}
				String str = isql.getFromExceptTarget();
				if (str != null && str.trim().length() > 0) {
					sqlSb.append(FROM);
					sqlSb.append(isql.getFromExceptTarget());
				}
				String cnds = isql.getConditions();

				if (atrbs != null) {
					if (cnds != null && !cnds.trim().equals("*")) {
						sqlSb.append(WHERE);
						sqlSb.append(cnds);
					}
				}
				else {
					sqlSb.append(WHERE);
					sqlSb.append(bAnalyzer.analyse(isql.getTargetType()).getPrimaryKeyName()
							+ " = ?");
				}
				break;
			}
				// delete
			case ObjectQuery.DELETE: {
				sqlSb.append(isql.getTarget());

				String str = isql.getConditions();
				if (str == null) {
					str = bAnalyzer.analyse(isql.getTargetType()).getPrimaryKeyName();
					if (str != null && str.length() > 0) {
						sqlSb.append(WHERE);
						sqlSb.append(str + " = ? ");
					}
					else {
						sqlSb.append(WHERE);
						String[] names = bAnalyzer.analyse(isql.getTargetType()).getDBNameOfAttributes();
						StringBufferTool.appendWithGap(sqlSb, names, " = ?"
								+ AND, AND);
					}
				}
				else
					if (!str.trim().equals("*")) {
						sqlSb.append(WHERE);
						sqlSb.append(str);
					}
				break;
			}

		}
		sql = sqlSb.toString();
		return sql;
	}

	public BuilderResult getSQL(QueryAssistor isql, Object paramObj)
			throws Exception {
		StringBuffer sqlSb = new StringBuffer();
		sqlSb.append(isql.getCmd());
		BuilderResult rslt = new BuilderResult();
		switch (isql.getCmdType()) {
			// insert
			case ObjectQuery.INSERT: {
				if (isql.hasAs()) { throw new ParametersMissMatch("no statements AS needed, while INSERT"); }
				sqlSb.append(isql.getTarget());
				sqlSb.append(" (");
				rslt.names = bAnalyzer.analyse(paramObj.getClass()).getDBNameOfAttributes(
																							paramObj);
				StringBufferTool.appendWithGap(sqlSb, rslt.names, ", ");
				sqlSb.append(" ) values (");
				StringBufferTool.appendWithGap(sqlSb, "?", rslt.names.length,
												", ", ", ");
				sqlSb.append(")");
				break;
			}
				// select
			case ObjectQuery.SELECT: {
				sqlSb.append(isql.getTarget());
				sqlSb.append(FROM);
				sqlSb.append(isql.getFrom());
				String str = isql.getConditions();
				if (str != null) {
					sqlSb.append(WHERE);
					sqlSb.append(str);
				}
				str = isql.getOrderBy();
				if (str != null) {
					sqlSb.append(" ");
					sqlSb.append(str);
				}
				str = isql.getPageInfro();
				if (str != null) {
					sqlSb.append(str);
				}
				break;
			}
				// update
			case ObjectQuery.UPDATE: {
				sqlSb.append(isql.getTarget());
				sqlSb.append(SET);
				String atrbs = isql.getAttributes();
				if (atrbs == null) {
					rslt.names = bAnalyzer.analyse(isql.getTargetType()).getDBNameOfAttributes();
					StringBufferTool.appendWithGap(sqlSb, rslt.names, " = ?, ",
													", ");
				}
				else {
					sqlSb.append(atrbs);
				}
				String cnds = isql.getConditions();

				if (atrbs != null) {
					if (cnds != null && !cnds.trim().equals("*")) {
						sqlSb.append(WHERE);
						sqlSb.append(cnds);
					}
				}
				else {
					sqlSb.append(WHERE);
					rslt.names = bAnalyzer.analyse(isql.getTargetType()).getDBNameOfAttributes();
					StringBufferTool.appendWithGap(sqlSb, rslt.names,
													" = ? and ", "and ");
				}
				break;
			}
				// delete
			case ObjectQuery.DELETE: {
				sqlSb.append(isql.getTarget());

				String str = isql.getConditions();
				if (str != null) {
					if (!str.trim().equals("*")) {
						sqlSb.append(WHERE);
						sqlSb.append(str);
					}
				}
				else {
					sqlSb.append(WHERE);
					rslt.names = bAnalyzer.analyse(isql.getTargetType()).getDBNameOfAttributes();
					StringBufferTool.appendWithGap(sqlSb, rslt.names, " = ?"
							+ AND, AND);
				}
				break;
			}

		}
		rslt.sql = sqlSb.toString();

		return rslt;
	}
}
